package com.studio49.exmple.common.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class MD5Utils {

	/**
	 * 默认MD5加密编码，UTF-8
	 */
	public final static String ENCODING = "UTF-8";

	/**
	 * 计算字节数组的MD5值
	 * 
	 * @param data
	 *            字节数组
	 * @return md5的字节数组
	 */
	public static byte[] md5(byte[] data) {
		try {
			MessageDigest md = MessageDigest.getInstance("md5");
			md.update(data);
			return md.digest();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return new byte[] {};
	}

	/**
	 * 计算字符串的md5值
	 * 
	 * @param data
	 *            输入的字符串
	 * @return md5值十六进制的字符串
	 */
	public static String md5(String data) {
		return md5(data, ENCODING);
	}

	/**
	 * 计算字符串的md5值
	 * 
	 * @param data
	 *            输入的字符串
	 * @param encoding
	 *            编码
	 * @return md5值十六进制的字符串
	 */
	public static String md5(String data, String encoding) {
		try {
			byte[] md5 = md5(data.getBytes(encoding));
			return toHexString(md5);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 将字节数组转为十六进制的字符串
	 * 
	 * @param md5
	 *            输入的字节数组
	 * @return 十六进制的字符串
	 */
	public static String toHexString(byte[] md5) {
		StringBuilder buf = new StringBuilder();
		for (byte b : md5) {
			buf.append(leftPad(Integer.toHexString(b & 0xff), '0', 2));
		}
		return buf.toString().toUpperCase();
	}

	/**
	 * 在字符串hex的左边填充字符c，填充的个数为size-hex长度
	 * 
	 * @param hex
	 *            十六进制的字符串
	 * @param c
	 *            要填充的字符
	 * @param size
	 *            填充完成后字符串的总长度
	 * @return 左边填充了字符c且长度为size的字符串
	 */
	private static String leftPad(String hex, char c, int size) {
		char[] cs = new char[size];
		Arrays.fill(cs, c);
		System.arraycopy(hex.toCharArray(), 0, cs, cs.length - hex.length(),
				hex.length());
		return new String(cs);
	}

	/**
	 * GBK模式MD5取值
	 * 
	 * @param data
	 *            字符串
	 * @return 字符串MD5取值
	 */
	public static String md5ByGbk(String data) {
		return md5(data, "GBK");
	}

	/**
	 * UTF-8模式MD5取值
	 * 
	 * @param data
	 *            字符串
	 * @return 字符串MD5取值
	 */
	public static String md5ByUtf8(String data) {
		return md5(data, "UTF-8");
	}

	/**
	 * GBK小写模式MD5取值
	 * 
	 * @param data
	 *            字符串
	 * @return 字符串MD5取值
	 */
	public static String md5ByGbkToLowerCase(String data) {
		return md5(data, "GBK").toLowerCase();
	}

	/**
	 * GBK小写模式MD5取值
	 * 
	 * @param data
	 *            字符串
	 * @return 字符串MD5取值
	 */
	public static String md5ByUtf8ToLowerCase(String data) {
		return md5(data, "UTF-8").toLowerCase();
	}

	/**
	 * 使用32位加密结果获取获取16位md5加密结果 32位结果中的第8到24位
	 * 
	 * @param data
	 *            32位加密结果
	 * @return 16位加密结果
	 */
	public static String get16Length(String data) {
		return data.substring(8, 24);
	}

	public static void main(String[] args) {
		System.out.println(md5("EDE0B6358FB738BBF64EC48A8C3BC012"));
	}
}
